/*
 * @(#) $Header$
 *
 * Copyright (C) 2006  Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.baselib.swing.event;

import java.util.HashMap;
import java.util.Map;

/**
 * Class {@code AbstractSwitchListener} provides a common framework to build
 * switch listeners. Switch listeners holds listeners with only one considered
 * active. Subclasses need to define the forwarding mechanism to the active
 * listener.
 * <p>
 * <strong>NOTE</strong> : the implementation is not synchronized.
 *
 * @param   <L>   the type of listener.
 *
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.baselib.swing.event.AbstractSwitchListener">Daniel Léonard</a>
 * @version $Revision$
 */
public abstract class AbstractSwitchListener<L> {

//---------------------------
// Instance variables
//---------------------------

   /** The listeners. */
   private Map<Object, L> listeners = new HashMap<>();

   /** The active listener. */
   private L active_listener;


//---------------------------
// Constructor
//---------------------------

   /**
    * Constructor. The active listener is set to the default listener.
    * @see   #getDefaultListener()
    */
   protected AbstractSwitchListener() {
      L default_listener = this.getDefaultListener();
      this.setActiveListener(default_listener);
      }


//---------------------------
// Accessors and mutators
//---------------------------

   /**
    * Gets the map of listeners.
    * @return   the map of listeners.
    */
   protected Map<Object, L> getListeners() {
      return this.listeners;
      }

   /**
    * Gets the active listener.
    * @return   the active listener.
    */
   protected L getActiveListener() {
      return this.active_listener;
      }

   /**
    * Changes the active listener.
    * @param   listener   the new listener.
    */
   protected void setActiveListener(L listener) {
      this.active_listener = listener;
      }


//---------------------------
// Abstract methods
//---------------------------

   /**
    * Gets the default listener for the switch.
    * @return   the listener.
    */
   protected abstract L getDefaultListener();


//---------------------------
// Instance methods
//---------------------------

   /**
    * Adds a new listener to the switch.
    * @param   key    the key of the listener.
    * @param   listener   the listener.
    */
   public void addListener(Object key, L listener) {
      Map<Object, L> map = this.getListeners();
      map.put(key, listener);
      }

   /**
    * Removes an action listener from the switch.
    * @param   key    the key of the listener.
    */
   public void removeListener(Object key) {
      Map<Object, L> map = this.getListeners();
      map.remove(key);
      this.switchTo(key);
      }

   /**
    * Sets the listener attached to the key as the active listener.
    * @param   key    the key of the listener.
    */
   public void switchTo(Object key) {
      Map<Object, L> map = this.getListeners();
      L listener = map.get(key);
      if (null == listener) {
         listener = this.getDefaultListener();
         }
      this.setActiveListener(listener);
      }

   }
